#include "max7219.h"
#include "fontlib.h"

#define MAX7219_NUM 4

MAX7219_Write_Data_t write_data;

uint8_t txBuf[MAX7219_NUM * 2] = {0};
uint8_t showBuffer[MAX7219_NUM * 8] = {0};

uint8_t *get_show_buffer()
{
    return showBuffer;
}

void LedRefresh(void)
{
    uint8_t i, j;
    for (i = 0; i < 8; i++)
    {
        for (j = 0; j < MAX7219_NUM; j++)
        {
            txBuf[j * 2] = i + 1;
            txBuf[j * 2 + 1] = *(showBuffer + (i * MAX7219_NUM) + j);
        }
        write_data(txBuf, (MAX7219_NUM * 2));
    }
}

void write_str_to_buf(uint8_t x, uint8_t y, char *str, int len, char_size_e size)
{
    uint8_t i;
    for (i = 0; i < len; i++)
    {
        if (size == SIZE_F5x7)
        {
            write_char_to_buf((x + (i * 5)), y, str[i], size);
        }
        else if (size == SIZE_F6X8)
        {
            write_char_to_buf((x + (i * 6)), y, str[i], size);
        }
    }
}

void write_char_to_buf(uint8_t x, uint8_t y, char c, char_size_e size)
{
    uint8_t i;
    uint32_t data_var;
    c = c - ' ';
    if (size == SIZE_F5x7)
    {
        for (i = 0; i < 7; i++)
        {
            if ((y + i) <= 8)
            {
                data_var = (uint32_t)(showBuffer[(y + i) * 4]) << 24;
                data_var = (uint32_t)(showBuffer[(y + i) * 4 + 1]) << 16 | data_var;
                data_var = (uint32_t)(showBuffer[(y + i) * 4 + 2]) << 8 | data_var;
                data_var = (uint32_t)(showBuffer[(y + i) * 4 + 3]) | data_var;

                if (x < 32)
                {
                    data_var &= ~(0xFC000000 >> x);
                    data_var |= ((uint32_t)F5x7[(uint8_t)c][i] << 24) >> x;
                }

                showBuffer[(y + i) * 4] = data_var >> 24;
                showBuffer[(y + i) * 4 + 1] = data_var >> 16 & 0xff;
                showBuffer[(y + i) * 4 + 2] = data_var >> 8 & 0xff;
                showBuffer[(y + i) * 4 + 3] = data_var;
            }
        }
    }
    else
    {
        for (i = 0; i < 8; i++)
        {
            if ((y + i) <= 8)
            {
                data_var = (uint32_t)(showBuffer[(y + i) * 4]) << 24;
                data_var = (uint32_t)(showBuffer[(y + i) * 4 + 1]) << 16 | data_var;
                data_var = (uint32_t)(showBuffer[(y + i) * 4 + 2]) << 8 | data_var;
                data_var = (uint32_t)(showBuffer[(y + i) * 4 + 3]) | data_var;

                if (x < 32)
                {
                    data_var &= ~(0xFC000000 >> x);
                    data_var |= ((uint32_t)F6x8[(uint8_t)c][i] << 24) >> x;
                }

                showBuffer[(y + i) * 4] = data_var >> 24;
                showBuffer[(y + i) * 4 + 1] = data_var >> 16 & 0xff;
                showBuffer[(y + i) * 4 + 2] = data_var >> 8 & 0xff;
                showBuffer[(y + i) * 4 + 3] = data_var;
            }
        }
    }
}

void clear_show()
{
    uint8_t i = 0;
    for (i = 0; i < sizeof(showBuffer); i++)
        showBuffer[i] = 0;
    LedRefresh();
}

int max7219Init(MAX7219_Write_Data_t cb)
{
    uint8_t i = 0;
    uint8_t reg = 0;
    uint8_t dat = 0;

    write_data = cb;

    // reg = 0x01 - 0x08         //显示位的数据地址

    reg = 0x09; // 译码方式寄存器    0x00:不译码;    0x01:BCD译码0位,1-7位不译码;
    dat = 0;    // 0x0F:BCD译码0-3位，4-7位不译码    0xFF:BCD译码0-7位
    for (i = 0; i < (MAX7219_NUM * 2); i += 2)
    {
        txBuf[i] = reg;
        txBuf[i + 1] = dat;
    }
    write_data(txBuf, (MAX7219_NUM * 2));

    reg = 0x0A; // 亮度寄存器  0x00-0x0F
    dat = 0x00;
    for (i = 0; i < (MAX7219_NUM * 2); i += 2)
    {
        txBuf[i] = reg;
        txBuf[i + 1] = dat;
    }
    write_data(txBuf, (MAX7219_NUM * 2));

    reg = 0x0B; // 扫描界限寄存器     0x00-0x07  扫描的位数
    dat = 0x07;
    for (i = 0; i < (MAX7219_NUM * 2); i += 2)
    {
        txBuf[i] = reg;
        txBuf[i + 1] = dat;
    }
    write_data(txBuf, (MAX7219_NUM * 2));

    reg = 0x0C; // 停机寄存器   0x00:停机状态； 0x01:正常状态
    dat = 0x01;
    for (i = 0; i < (MAX7219_NUM * 2); i += 2)
    {
        txBuf[i] = reg;
        txBuf[i + 1] = dat;
    }
    write_data(txBuf, (MAX7219_NUM * 2));

    reg = 0x0F; // 显示测试寄存器  0x00:正常状态，0x01 测试状态，所有位最大亮度显示
    dat = 0x00;
    for (i = 0; i < (MAX7219_NUM * 2); i += 2)
    {
        txBuf[i] = reg;
        txBuf[i + 1] = dat;
    }
    write_data(txBuf, (MAX7219_NUM * 2));

    clear_show();

    return 0;
}
